<template>
  <div class="upload flex gap-2 items-center">
    <div class="file-list flex gap-2">
      <div v-for="(item, index) in modelValue ?? []" :key="index" class="w-[100px] h-[100px]">
        <img :src="loadFileTypeImg(item)" alt="" class="w-full h-full object-contain" />
        <div class="truncate text-14 text-[#666] text-center">
          {{ item.fileName }}
        </div>
      </div>
    </div>
    <el-upload
      v-if="(modelValue?.length ?? 0) < (limit ?? 1)"
      action="#"
      :accept="accept ?? '*'"
      :limit="limit ?? 1"
      :class="className"
      :drag="drag ?? false"
      :list-type="listType ?? 'text'"
      :multiple="false"
      :show-file-list="false"
      :before-upload="handleBeforeUpload"
      :http-request="handleHttpRequest"
    >
      <div v-if="drag">
        <el-icon class="el-icon--upload"><UploadFilled /></el-icon>
        <span class="text-12 text-[#999] truncate w-full mt-1">{{
          dragText ?? '将文件拖放到此处'
        }}</span>
      </div>
      <div v-else>
        <el-icon v-if="!listType || listType === 'picture-card'"><Plus /></el-icon>
        <el-button v-else type="primary">{{ btnText ?? '上传文件' }}</el-button>
      </div>
    </el-upload>
  </div>
</template>
<script lang="ts" setup name="Upload">
import moment from 'moment'
import { cloneDeep } from 'lodash'
import { ElMessage } from 'element-plus'
import { AxiosProgressEvent } from 'axios'
import { Plus, UploadFilled } from '@element-plus/icons-vue'
import { UploadRequestOptions, UploadRawFile } from 'element-plus/es/components/upload/src/upload'
import { fileUploadApi } from '@/api/upload'

type FileInfoType = {
  fileName: string
  fileSize: string
  filePath: string
  fileType: string
  fileUploadTime: string
}
const emit = defineEmits(['update:modelValue'])
const props = defineProps<{
  modelValue: FileInfoType[] | undefined
  limit?: number
  drag?: boolean
  listType?: string
  btnText?: string
  dragText?: string
  size?: number
  accept?: string
  className?: string
}>()

const handleDeleteFileItem = (index: number) => {
  const cloneModelValue = cloneDeep(props.modelValue ?? [])
  cloneModelValue.splice(index, 1)
  emit('update:modelValue', cloneModelValue)
}

// 将字节转换为KB、MB、GB
function bytesToSize(bytes: number) {
  const kilobytes = bytes / 1024
  if (kilobytes > 1024) {
    const megabytes = kilobytes / 1024
    if (megabytes > 1024) {
      const gigabytes = megabytes / 1024
      return gigabytes.toFixed(2) + 'G'
    }
    return megabytes.toFixed(2) + 'MB'
  }
  return kilobytes.toFixed(2) + 'KB'
}
const handleHttpRequest = async (option: UploadRequestOptions) => {
  try {
    const { file } = option
    const formData = new FormData()
    formData.append('file', file)
    const { code, data } = await fileUploadApi(formData, (val: AxiosProgressEvent) => {
      handleProgress(val)
    })
    if (code === 0 && data) {
      ElMessage.success('上传成功')
      console.log(getFileType(file))
      emit('update:modelValue', [
        ...(props.modelValue ?? []),
        {
          fileName: file.name,
          fileSize: bytesToSize(file.size),
          filePath: data,
          fileType: getFileType(file),
          fileUploadTime: moment().format('YYYY-MM-DD HH:mm:ss')
        }
      ])
    }
  } catch (e) {
    console.log(e)
  }
}

/**************** 其他文件类型图片路径匹配 *****************/
// 匹配图片模块
const imgModule = import.meta.glob('/src/assets/img/upload/**.png', {
  eager: true,
  import: 'default'
})
// 获取文件实际类型
const getFileType = (file: UploadRawFile): string | boolean => {
  if (
    file.type.includes('image/') ||
    file.type.includes('video/') ||
    file.type.includes('audio/')
  ) {
    return file.type.split('/')[0]
  }
  const fileExtension = file.name.split('.').pop()?.toLowerCase()
  if (!fileExtension) {
    ElMessage.error('未知文件类型')
    return false
  }
  if (['pdf', 'doc', 'xls', 'ppt', 'ttf', 'json', 'zip'].includes(fileExtension)) {
    return fileExtension
  }
  if (['rar', '7z', 'tar', 'arj', 'jar'].includes(fileExtension)) {
    return 'zip'
  }
  if (['docx', 'xlsx', 'pptx'].includes(fileExtension)) {
    return fileExtension.slice(0, -1)
  }
  return 'other'
}
// 加载图片
const loadFileTypeImg = (fileItem: FileInfoType): string => {
  const { fileType, filePath } = fileItem
  return fileType === 'image'
    ? `${import.meta.env.VITE_BASE_API}${filePath}`
    : ((imgModule[`/src/assets/img/upload/${fileType}.png`] ?? '') as string)
}
const handleProgress = (e: AxiosProgressEvent) => {
  console.log(e)
}
// 上传前判断文件大小 是否运行上传
const handleBeforeUpload = (rawFile: UploadRawFile) => {
  const allowedMaxFileSize = props.size ?? 5
  if (rawFile.size > 1024 * 1024 * allowedMaxFileSize) {
    ElMessage.error(`文件大小不能超过${allowedMaxFileSize}MB!`)
    return false
  }
  return true
}
</script>
<style lang="scss" scoped>
:deep(.el-upload--picture-card) {
  --el-upload-picture-card-size: 100px;
  .el-upload-dragger {
    height: 100%;
    background: transparent;
    & > div {
      height: 100%;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      i {
        font-size: 24px;
      }
    }
  }
  i {
    font-size: 16px;
  }
}
</style>
